`timescale 1ns / 1ps
   
module tb_sm3_top();

    // Inputs
    reg clk;
    reg rst_n;
    reg [31:0] msg_inpt_d;
    reg [3:0] msg_inpt_vld_byte;
    reg msg_inpt_vld;
    reg msg_inpt_lst;
    
    // Outputs
    wire msg_inpt_rdy;
    wire [255:0] cmprss_otpt_res;
    wire cmprss_otpt_vld;
    
    // Instantiate the Unit Under Test (UUT)
    sm3_top uut (
        .clk(clk),
        .rst_n(rst_n),
        .msg_inpt_d(msg_inpt_d),
        .msg_inpt_vld_byte(msg_inpt_vld_byte),
        .msg_inpt_vld(msg_inpt_vld),
        .msg_inpt_lst(msg_inpt_lst),
        .msg_inpt_rdy(msg_inpt_rdy),
        .cmprss_otpt_res(cmprss_otpt_res),
        .cmprss_otpt_vld(cmprss_otpt_vld)
    );
    
    // Clock generation
    initial begin
        clk = 0;
        forever #5 clk = ~clk;
    end
    
    // Expected hash value for "abc"
    // 66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b84ba8e0
    reg [255:0] expected_hash = 256'h66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b84ba8e0;
    
    // Test sequence
    initial begin
        // Initialize Inputs
        rst_n = 0;
        msg_inpt_d = 0;
        msg_inpt_vld_byte = 0;
        msg_inpt_vld = 0;
        msg_inpt_lst = 0;
        
        // Wait 100 ns for global reset to finish
        #100;
        rst_n = 1;
        
        // Wait for the module to be ready
        wait(msg_inpt_rdy == 1);
        #20;
        
        // Send first 32-bit word (0x61626300) - 'a','b','c', padding starts
        msg_inpt_d = 32'h61626380;  // 'a'(61), 'b'(62), 'c'(63), padding starts with 0x80
        msg_inpt_vld_byte = 4'b0111; // First 3 bytes are valid
        msg_inpt_vld = 1;            // This is the last message block
        msg_inpt_lst = 1;            // Indicate last block with partial bytes
        
        #10;
        msg_inpt_vld = 0;
        msg_inpt_lst = 0;
        
        // Wait for the output to be valid
        wait(cmprss_otpt_vld == 1);
        
        // Check the result
        if (cmprss_otpt_res === expected_hash) begin
            $display("[PASS] Hash output matches expected value");
            $display("Output:   %64h", cmprss_otpt_res);
            $display("Expected: %64h", expected_hash);
        end
        else begin
            $display("[FAIL] Hash output does not match expected value");
            $display("Output:   %64h", cmprss_otpt_res);
            $display("Expected: %64h", expected_hash);
        end
        
        // Add some margin before ending simulation
        #100;
        $finish;
    end
    
    // Monitor signals
    initial begin
        $monitor("Time = %t: msg_inpt_rdy = %b, cmprss_otpt_vld = %b, hash = %64h", 
                 $time, msg_inpt_rdy, cmprss_otpt_vld, cmprss_otpt_res);
    end
    
endmodule
